package com.xiaowen.wxpaytool;


import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xiaowen.wxpaytool.modle.PrepayRequest;
import com.xiaowen.wxpaytool.modle.PaybodyInfo;
import com.xiaowen.wxpaytool.modle.RefundRequest;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.UUID;

public class WxpayV3Tool {
    @Autowired
    WxPayProperties wxPayProperties;
    @Autowired
    TokenUtil tokenUtil;
    private  String url_prex="https://api.mch.weixin.qq.com/";
    private String charset = "UTF-8";


    //1获得预付单号
    public String getprepayinfo(PrepayRequest prepayRequest) throws Exception {
        JSONObject jsonObject=tokenUtil.sendPostV3("v3/pay/transactions/jsapi",JSONUtil.toJsonStr(prepayRequest));
        return jsonObject.getStr("prepay_id");
//        switch (clienttype) {
//            case "v3/pay/transactions/app":
//            case "v3/pay/transactions/jsapi":
//                return jsonObject.getStr("prepay_id");
//            case "v3/pay/transactions/native":
//                return jsonObject.getStr("code_url");
//            case "v3/pay/transactions/h5":
//                return jsonObject.getStr("h5_url");
//            default:
//                return null;
//        }
    }
    //1.2生成客户端支付请求的参数
    public PaybodyInfo getpaybodyinfo(String prepayid) throws Exception {
        String time = System.currentTimeMillis() / 1000 + "";
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        String packageStr = "prepay_id=" + prepayid;
        ArrayList<String> list = new ArrayList<>();
        list.add(wxPayProperties.getAppid());
        list.add(time);
        list.add(nonceStr);
        list.add(packageStr);
        //加载签名
        String packageSign = tokenUtil.sign(tokenUtil.buildSignMessage(list).getBytes(), wxPayProperties.getPrivatekeypemfilepath());
        PaybodyInfo paybodyInfo = new PaybodyInfo(wxPayProperties.getAppid(), time, nonceStr, packageStr, "RSA", packageSign);
        return paybodyInfo;
    }


    //2根据系统订单号查询支付单详情
    public  JSONObject selectPayByOutTradeNo(String out_trade_no) throws Exception {
        String geturl=url_prex+"v3/pay/transactions/out-trade-no/"+out_trade_no+"?mchid="+wxPayProperties.getMchid();
        String postToken = tokenUtil.getpostTokenv3("GET", HttpUrl.parse(geturl),
                wxPayProperties.getMchid(), wxPayProperties.getMchserialno(), wxPayProperties.getPrivatekeypemfilepath(), "");
        JSONObject body = null;
        //创建httpclient对象
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(geturl)
                .addHeader("Accept","application/json")
                .addHeader("Authorization","WECHATPAY2-SHA256-RSA2048 " + postToken)
                .build();
        Response response = client.newCall(request).execute();
        return JSONUtil.parseObj(response.body().string());
    }
    //2根据支付单号查询支付单详情
    public  JSONObject selectPayByTransactionId(String transactionid) throws Exception {
        String geturl=url_prex+"v3/pay/transactions/id/"+transactionid+"?mchid="+wxPayProperties.getMchid();
        String postToken = tokenUtil.getpostTokenv3("GET", HttpUrl.parse(geturl),
                wxPayProperties.getMchid(), wxPayProperties.getMchserialno(), wxPayProperties.getPrivatekeypemfilepath(), "");
        JSONObject body = null;
        //创建httpclient对象
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(geturl)
                .addHeader("Accept","application/json")
                .addHeader("Authorization","WECHATPAY2-SHA256-RSA2048 " + postToken)
                .build();
        Response response = client.newCall(request).execute();
        return JSONUtil.parseObj(response.body().string());
    }
    //3、关闭支付单
    public void closePay(String out_trade_no) throws Exception {
        String posturl="v3/pay/transactions/out-trade-no/"+out_trade_no+"/close";
        JSONObject mchidjson = new JSONObject();
        mchidjson.putOnce("mchid", wxPayProperties.getMchid());
        String body = "";
        OkHttpClient client = new OkHttpClient();
        String postToken = tokenUtil.getpostTokenv3("POST", HttpUrl.parse(url_prex+posturl), wxPayProperties.getMchid(), wxPayProperties.getMchserialno(), wxPayProperties.getPrivatekeypemfilepath(), JSONUtil.toJsonStr(mchidjson));
        RequestBody requestBody = RequestBody.create( MediaType.parse("application/json; charset=utf-8"),JSONUtil.toJsonStr(mchidjson));
        Request request = new Request.Builder()
                .url(url_prex+posturl)
                .addHeader("Accept","application/json")
                .addHeader("Authorization","WECHATPAY2-SHA256-RSA2048 " + postToken)
                .post(requestBody)
                .build();
        Response response = client.newCall(request).execute();
    }

   //4、支付回调/退单回调
    public JSONObject notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String result = tokenUtil.readData(request);
        // 需要通过证书序列号查找对应的证书，verifyNotify 中有验证证书的序列号
        String plainText = tokenUtil.verifyNotify(result, wxPayProperties.getApiv3key());
        //发送消息通知微信
        tokenUtil.sendMessage(response, plainText);
        JSONObject jsonObject= JSONUtil.parseObj(plainText);
        return jsonObject;
    }


    //5、申请退款
    public JSONObject refundOrder(RefundRequest refundRequest) throws Exception {
        JSONObject jsonObject= tokenUtil.sendPostV3( "v3/refund/domestic/refunds",JSONUtil.toJsonStr(refundRequest));
        return jsonObject;
    }
    //6、根据退款系统订单号查退款单
    public  JSONObject selectRefundByOutTradeNo(String out_trade_no) throws Exception {
        String geturl=url_prex+"v3/refund/domestic/refunds/"+out_trade_no;
        String postToken = tokenUtil.getpostTokenv3("GET", HttpUrl.parse(geturl),
                wxPayProperties.getMchid(), wxPayProperties.getMchserialno(), wxPayProperties.getPrivatekeypemfilepath(), "");
        JSONObject body = null;
        //创建httpclient对象
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(geturl)
                .addHeader("Accept","application/json")
                .addHeader("Authorization","WECHATPAY2-SHA256-RSA2048 " + postToken)
                .build();
        Response response = client.newCall(request).execute();
        return JSONUtil.parseObj(response.body().string());
    }



    //7支付账单
    public JSONObject selectTradebill(String date) throws Exception {
        String geturl=url_prex+"v3/bill/tradebill?bill_date="+date;
        String postToken = tokenUtil.getpostTokenv3("GET", HttpUrl.parse(geturl),
                wxPayProperties.getMchid(), wxPayProperties.getMchserialno(), wxPayProperties.getPrivatekeypemfilepath(), "");
        JSONObject body = null;
        //创建httpclient对象
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(geturl)
                .addHeader("Accept","application/json")
                .addHeader("Authorization","WECHATPAY2-SHA256-RSA2048 " + postToken)
                .build();
        Response response = client.newCall(request).execute();
        return JSONUtil.parseObj(response.body().string());
    }
    //8资金账单
    public JSONObject selectFundflowBill(String date) throws Exception {
        String geturl=url_prex+"v3/bill/fundflowbill?bill_date="+date;
        String postToken = tokenUtil.getpostTokenv3("GET", HttpUrl.parse(geturl),
                wxPayProperties.getMchid(), wxPayProperties.getMchserialno(), wxPayProperties.getPrivatekeypemfilepath(), "");
        JSONObject body = null;
        //创建httpclient对象
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(geturl)
                .addHeader("Accept","application/json")
                .addHeader("Authorization","WECHATPAY2-SHA256-RSA2048 " + postToken)
                .build();
        Response response = client.newCall(request).execute();
        return JSONUtil.parseObj(response.body().string());
    }
}
